using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;

using System.IO;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.Threading;
using System.Collections.Generic;

namespace RequiredCheckboxFieldTypeSolution
{
    public class RequiredCheckboxField : SPFieldBoolean
    {
        private const string THREADDATANAME_TEXT = "Text";
        private const string THREADDATANAME_ERRORMESSAGE = "ErrorMessage";

        #region Private fields
        private string _text;
        private string _errormessage;
        private bool _preventUpdate = false;
        #endregion

        #region Constructors
        public RequiredCheckboxField(SPFieldCollection fields, string fieldName)
            : base(fields, fieldName)
        {
        }

        public RequiredCheckboxField(SPFieldCollection fields, string typeName, string displayName)
            : base(fields, typeName, displayName)
        {
        }
        #endregion

        #region Methods used for temporary storage
        /// <summary>
        /// http://msdn.microsoft.com/en-us/library/cc889345.aspx
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="value"></param>
        protected void SetNamedThreadData(string propertyName, object value)
        {
            Thread.SetData(Thread.GetNamedDataSlot(propertyName), value);
        }

        protected void ClearNamedThreadData(string propertyName)
        {
            Thread.FreeNamedDataSlot(propertyName);
        }

        protected object GetNamedThreadData(string propertyName)
        {
            return Thread.GetData(Thread.GetNamedDataSlot(propertyName));
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Returns an specialized FieldControl for this Field/FieldType
        /// </summary>
        public override Microsoft.SharePoint.WebControls.BaseFieldControl FieldRenderingControl
        {
            get
            {
                BaseFieldControl control = new RequiredCheckboxFieldControl();
                control.FieldName = this.InternalName;
                return control;
            }
        }

        public string Text
        {
            get
            {
                if (_text == null)
                {
                    string value = (string)GetCustomProperty("Text");
                    _text = (value != null) ? value : null;
                }

                return _text;
            }
            set
            {
                string fv = null;
                if (!string.IsNullOrEmpty(value)) fv = value;
                _text = value;
                SetNamedThreadData(THREADDATANAME_TEXT, fv);
            }
        }

        public string ErrorMessage
        {
            get
            {
                if (_errormessage == null)
                {
                    string value = (string)GetCustomProperty("ErrorMessage");
                    _errormessage = (value != null) ? value : null;
                }
                
                return _errormessage;
            }
            set
            {
                string fv = null;
                if (!string.IsNullOrEmpty(value)) fv = value;
                _errormessage = value;
                SetNamedThreadData(THREADDATANAME_ERRORMESSAGE, fv);
            }
        }
        #endregion

        #region Public methods
        /// <summary>
        /// override the OnAdded method to call Update
        /// because Update is not called when creating new fields 
        /// </summary>
        public override void OnAdded(SPAddFieldOptions op)
        {
            _preventUpdate = true;
            string text = (string)GetNamedThreadData(THREADDATANAME_TEXT);
            SetCustomProperty("Text", text);

            string errormessage = (string)GetNamedThreadData(THREADDATANAME_TEXT);
            SetCustomProperty("ErrorMessage", errormessage);

            Update();
            ClearNamedThreadData(THREADDATANAME_TEXT);
            ClearNamedThreadData(THREADDATANAME_ERRORMESSAGE);
        }

        public override void OnUpdated()
        {
            if (_preventUpdate == false)
            {
                _preventUpdate = true;

                string text = (string)GetNamedThreadData(THREADDATANAME_TEXT);
                SetCustomProperty("Text", text);

                string errormessage = (string)GetNamedThreadData(THREADDATANAME_ERRORMESSAGE);
                SetCustomProperty("ErrorMessage", errormessage);

                Update();
                ClearNamedThreadData(THREADDATANAME_TEXT);
                ClearNamedThreadData(THREADDATANAME_ERRORMESSAGE);
            }
        }

        public override object GetFieldValue(string value)
        {
            return value;
        }

        #endregion
    }
}
